﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace QS
{
    class QSkyBox
    {
        private const int SIZE = 500;

        public BasicEffect mcEffect = null;

        VertexBuffer mcVertexBuffer = null;
        IndexBuffer mcIndexBuffer = null;

        Texture2D[] mcaTextures = null;

        public void Load(GraphicsDevice graphicsDevice, ContentManager contentManager)
        {
            mcaTextures = new Texture2D[6];
            mcaTextures[0] = contentManager.Load<Texture2D>("stars_skybox");
            mcaTextures[1] = mcaTextures[0];
            mcaTextures[2] = mcaTextures[0];
            mcaTextures[3] = mcaTextures[0];
            mcaTextures[4] = mcaTextures[0];
            mcaTextures[5] = mcaTextures[0];

            SetupVertices(graphicsDevice);
            SetupIndices(graphicsDevice);

            mcEffect = new BasicEffect(graphicsDevice);
            mcEffect.TextureEnabled = true;
        }

        public void Draw(GraphicsDevice device, QCamera camera, SpriteBatch spriteBatch)
        {
            if (mcVertexBuffer == null)
                return;

            // Translate the Sky Box to keep it at a constant distance from the Camera
            Matrix sWorld = Matrix.CreateTranslation(camera.Position);

            // Setup the World, View, and Projection Matrices
            mcEffect.World = sWorld;
            mcEffect.View = camera.ViewMatrix;
            mcEffect.Projection = camera.ProjectionMatrix;

            // Set the Vertex and Index Buffers to use
            device.SetVertexBuffer(mcVertexBuffer);
            device.Indices = mcIndexBuffer;

            // Loop through all 6 sides of the Sky Box
            for (int iSide = 0; iSide < 6; iSide++)
            {
                // Set the proper Texture to use to draw this Side of the Sky Box
                mcEffect.Texture = mcaTextures[iSide];

				int numberOfPasses = mcEffect.CurrentTechnique.Passes.Count;
				for (int passIndex = 0; passIndex < numberOfPasses; passIndex++)
				{
					// Get a handle to the pass
					EffectPass cPass = mcEffect.CurrentTechnique.Passes[passIndex];
					cPass.Apply();

					// Draw this Side of the Sky Box
                    device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, iSide * 4, 4, iSide * 6, 2);
				}
            }
        }

        private void SetupVertices(GraphicsDevice device)
        {
            // Create array to hold the Vertices
            VertexPositionTexture[] saVertices = new VertexPositionTexture[4 * 6];

            // Calculate Half of the Sky Boxes Size
            Vector3 sHalfSkyBoxSize = new Vector3(SIZE / 2, SIZE / 2, SIZE / 2);

            // Back of Sky Box
            saVertices[0].Position = new Vector3(sHalfSkyBoxSize.X, -sHalfSkyBoxSize.Y, -sHalfSkyBoxSize.Z);
            saVertices[0].TextureCoordinate.X = 1.0f; saVertices[0].TextureCoordinate.Y = 1.0f;
            saVertices[1].Position = new Vector3(sHalfSkyBoxSize.X, sHalfSkyBoxSize.Y, -sHalfSkyBoxSize.Z);
            saVertices[1].TextureCoordinate.X = 1.0f; saVertices[1].TextureCoordinate.Y = 0.0f;
            saVertices[2].Position = new Vector3(-sHalfSkyBoxSize.X, sHalfSkyBoxSize.Y, -sHalfSkyBoxSize.Z);
            saVertices[2].TextureCoordinate.X = 0.0f; saVertices[2].TextureCoordinate.Y = 0.0f;
            saVertices[3].Position = new Vector3(-sHalfSkyBoxSize.X, -sHalfSkyBoxSize.Y, -sHalfSkyBoxSize.Z);
            saVertices[3].TextureCoordinate.X = 0.0f; saVertices[3].TextureCoordinate.Y = 1.0f;

            // Front of Sky Box
            saVertices[4].Position = new Vector3(-sHalfSkyBoxSize.X, -sHalfSkyBoxSize.Y, sHalfSkyBoxSize.Z);
            saVertices[4].TextureCoordinate.X = 1.0f; saVertices[4].TextureCoordinate.Y = 1.0f;
            saVertices[5].Position = new Vector3(-sHalfSkyBoxSize.X, sHalfSkyBoxSize.Y, sHalfSkyBoxSize.Z);
            saVertices[5].TextureCoordinate.X = 1.0f; saVertices[5].TextureCoordinate.Y = 0.0f;
            saVertices[6].Position = new Vector3(sHalfSkyBoxSize.X, sHalfSkyBoxSize.Y, sHalfSkyBoxSize.Z);
            saVertices[6].TextureCoordinate.X = 0.0f; saVertices[6].TextureCoordinate.Y = 0.0f;
            saVertices[7].Position = new Vector3(sHalfSkyBoxSize.X, -sHalfSkyBoxSize.Y, sHalfSkyBoxSize.Z);
            saVertices[7].TextureCoordinate.X = 0.0f; saVertices[7].TextureCoordinate.Y = 1.0f;

            // Bottom of Sky Box
            saVertices[8].Position = new Vector3(-sHalfSkyBoxSize.X, -sHalfSkyBoxSize.Y, -sHalfSkyBoxSize.Z);
            saVertices[8].TextureCoordinate.X = 0.0f; saVertices[8].TextureCoordinate.Y = 0.0f;
            saVertices[9].Position = new Vector3(-sHalfSkyBoxSize.X, -sHalfSkyBoxSize.Y, sHalfSkyBoxSize.Z);
            saVertices[9].TextureCoordinate.X = 0.0f; saVertices[9].TextureCoordinate.Y = 1.0f;
            saVertices[10].Position = new Vector3(sHalfSkyBoxSize.X, -sHalfSkyBoxSize.Y, sHalfSkyBoxSize.Z);
            saVertices[10].TextureCoordinate.X = 1.0f; saVertices[10].TextureCoordinate.Y = 1.0f;
            saVertices[11].Position = new Vector3(sHalfSkyBoxSize.X, -sHalfSkyBoxSize.Y, -sHalfSkyBoxSize.Z);
            saVertices[11].TextureCoordinate.X = 1.0f; saVertices[11].TextureCoordinate.Y = 0.0f;

            // Top of Sky Box
            saVertices[12].Position = new Vector3(sHalfSkyBoxSize.X, sHalfSkyBoxSize.Y, -sHalfSkyBoxSize.Z);
            saVertices[12].TextureCoordinate.X = 1.0f; saVertices[12].TextureCoordinate.Y = 0.0f;
            saVertices[13].Position = new Vector3(sHalfSkyBoxSize.X, sHalfSkyBoxSize.Y, sHalfSkyBoxSize.Z);
            saVertices[13].TextureCoordinate.X = 1.0f; saVertices[13].TextureCoordinate.Y = 1.0f;
            saVertices[14].Position = new Vector3(-sHalfSkyBoxSize.X, sHalfSkyBoxSize.Y, sHalfSkyBoxSize.Z);
            saVertices[14].TextureCoordinate.X = 0.0f; saVertices[14].TextureCoordinate.Y = 1.0f;
            saVertices[15].Position = new Vector3(-sHalfSkyBoxSize.X, sHalfSkyBoxSize.Y, -sHalfSkyBoxSize.Z);
            saVertices[15].TextureCoordinate.X = 0.0f; saVertices[15].TextureCoordinate.Y = 0.0f;

            // Left side of Sky Box
            saVertices[16].Position = new Vector3(sHalfSkyBoxSize.X, -sHalfSkyBoxSize.Y, -sHalfSkyBoxSize.Z);
            saVertices[16].TextureCoordinate.X = 0.0f; saVertices[19].TextureCoordinate.Y = 0.0f;
            saVertices[17].Position = new Vector3(sHalfSkyBoxSize.X, -sHalfSkyBoxSize.Y, sHalfSkyBoxSize.Z);
            saVertices[17].TextureCoordinate.X = 1.0f; saVertices[18].TextureCoordinate.Y = 0.0f;
            saVertices[18].Position = new Vector3(sHalfSkyBoxSize.X, sHalfSkyBoxSize.Y, sHalfSkyBoxSize.Z);
            saVertices[18].TextureCoordinate.X = 1.0f; saVertices[17].TextureCoordinate.Y = 1.0f;
            saVertices[19].Position = new Vector3(sHalfSkyBoxSize.X, sHalfSkyBoxSize.Y, -sHalfSkyBoxSize.Z);
            saVertices[19].TextureCoordinate.X = 0.0f; saVertices[16].TextureCoordinate.Y = 1.0f;

            // Right side of Sky Box            
            saVertices[20].Position = new Vector3(-sHalfSkyBoxSize.X, sHalfSkyBoxSize.Y, -sHalfSkyBoxSize.Z);
            saVertices[20].TextureCoordinate.X = 1.0f; saVertices[23].TextureCoordinate.Y = 1.0f;
            saVertices[21].Position = new Vector3(-sHalfSkyBoxSize.X, sHalfSkyBoxSize.Y, sHalfSkyBoxSize.Z);
            saVertices[21].TextureCoordinate.X = 0.0f; saVertices[22].TextureCoordinate.Y = 1.0f;
            saVertices[22].Position = new Vector3(-sHalfSkyBoxSize.X, -sHalfSkyBoxSize.Y, sHalfSkyBoxSize.Z);
            saVertices[22].TextureCoordinate.X = 0.0f; saVertices[21].TextureCoordinate.Y = 0.0f;
            saVertices[23].Position = new Vector3(-sHalfSkyBoxSize.X, -sHalfSkyBoxSize.Y, -sHalfSkyBoxSize.Z);
            saVertices[23].TextureCoordinate.X = 1.0f; saVertices[20].TextureCoordinate.Y = 0.0f;

            // Copy the Vertex data to the Vertex Buffer
            mcVertexBuffer = new VertexBuffer(device, VertexPositionTexture.VertexDeclaration, saVertices.Length, BufferUsage.WriteOnly);
            mcVertexBuffer.SetData(saVertices);
        }

        private void SetupIndices(GraphicsDevice device)
        {
            // Create an array to hold the Indices
            int[] miaIndices = new int[6 * 6];

            for (int x = 0; x < 6; x++)
            {
                miaIndices[x * 6 + 0] = (short)(x * 4 + 0);
                miaIndices[x * 6 + 2] = (short)(x * 4 + 1);
                miaIndices[x * 6 + 1] = (short)(x * 4 + 2);

                miaIndices[x * 6 + 3] = (short)(x * 4 + 2);
                miaIndices[x * 6 + 5] = (short)(x * 4 + 3);
                miaIndices[x * 6 + 4] = (short)(x * 4 + 0);
            }

            // Copy the Index data to the Index Buffer
            mcIndexBuffer = new IndexBuffer(device, typeof(int), miaIndices.Length, BufferUsage.WriteOnly);
            mcIndexBuffer.SetData(miaIndices);
        }
    }
}
